/**
 * This file is part of Idegen, the application to create IDE project files.
 *
 * @copyright Copyright (c) 2011-2012, Walter Tamboer http://waltertamboer.nl
 * @file Idegen/Idegen/IdegenProjectFilter.cpp
 */

#include "Idegen/PrecompiledHeader.hpp"
#include "Idegen/IO/File.hpp"
#include "Idegen/Idegen/IdegenProjectFile.hpp"
#include "Idegen/Idegen/IdegenProjectFilter.hpp"

namespace Idegen
{
	IdegenProjectFilter::IdegenProjectFilter( const std::string& name )
		: m_Parent( NULL )
	{
		ProjectFilterNameList nameList;
		if ( ParseFilterNames( name, nameList ) )
		{
			// Remove the first one:
			m_Name = nameList[ 0 ];
			nameList.erase( nameList.begin() );

			if ( !nameList.empty() )
			{
				std::string path;
				for ( size_t i = 0; i < nameList.size(); ++i )
				{
					path += i == 0 ? nameList[ i ] : "/" + nameList[ i ];
				}
				AddFilter( path, this );
			}
		}
		else
		{
			m_Name = name;
		}
	}

	IdegenProjectFilter::IdegenProjectFilter( const std::string& name, IdegenProjectFilter* parent )
		: m_Parent( parent )
	{
		ProjectFilterNameList nameList;
		if ( ParseFilterNames( name, nameList ) )
		{
			// Remove the first one:
			m_Name = nameList[ 0 ];
			nameList.erase( nameList.begin() );

			if ( !nameList.empty() )
			{
				std::string path;
				for ( size_t i = 0; i < nameList.size(); ++i )
				{
					path += i == 0 ? nameList[ i ] : "/" + nameList[ i ];
				}
				AddFilter( path, this );
			}
		}
		else
		{
			m_Name = name;
		}
	}

	IdegenProjectFilter::~IdegenProjectFilter()
	{
		for ( ProjectFilterList::iterator it = m_Filters.begin(); it != m_Filters.end(); ++it )
		{
			delete (*it);
		}
		
		for ( ProjectFileList::iterator it = m_Files.begin(); it != m_Files.end(); ++it )
		{
			delete (*it);
		}
	}

	std::string IdegenProjectFilter::GetName() const
	{
		return m_Name;
	}

	std::string IdegenProjectFilter::GetFullName() const
	{
		std::string result = m_Name;

		IdegenProjectFilter* parent = m_Parent;
		while ( parent != NULL && !parent->m_Name.empty() )
		{
			result = parent->m_Name + "\\" + result;
			parent = parent->m_Parent;
		}

		return result;
	}

	void IdegenProjectFilter::AddFile( IdegenProjectFile* file )
	{
		m_Files.push_back( file );
	}

	IdegenProjectFilter* IdegenProjectFilter::AddFilter( const std::string& name, IdegenProjectFilter* parentFilter )
	{
		IdegenProjectFilter* result = FindFilter( name );

		if ( result == NULL )
		{
			ProjectFilterNameList nameList;
			if ( ParseFilterNames( name, nameList ) )
			{
				result = this;
				for ( ProjectFilterNameList::iterator it = nameList.begin(); it != nameList.end(); ++it )
				{
					parentFilter = result;
					result = result->AddFilter( (*it), parentFilter );
				}
			}
			else
			{
				result = new IdegenProjectFilter( name, parentFilter );
				m_Filters.push_back( result );
			}
		}

		return result;
	}

	IdegenProjectFilter* IdegenProjectFilter::FindFilter( const std::string& name ) const
	{
		IdegenProjectFilter* result = NULL;

		for ( ProjectFilterList::const_iterator it = m_Filters.begin(); it != m_Filters.end(); ++it )
		{
			if ( (*it)->GetName() == name )
			{
				result = (*it);
				break;
			}
		}

		return result;
	}

	ProjectFileList IdegenProjectFilter::GetFiles( bool allFiles ) const
	{
		ProjectFileList result = m_Files;
		if ( allFiles )
		{
			for ( ProjectFilterList::const_iterator it = m_Filters.begin(); it != m_Filters.end(); ++it )
			{
				ProjectFileList children = (*it)->GetFiles( true );
				result.insert( result.end(), children.begin(), children.end() );
			}
		}
		return result;
	}

	ProjectFilterList IdegenProjectFilter::GetFilters() const
	{
		return m_Filters;
	}

	bool IdegenProjectFilter::ParseFilterNames( const std::string& path, ProjectFilterNameList& nameList )
	{
		std::string pathToParse = path;

		std::string::size_type currPosition = pathToParse.find_first_of( TEXT('/') );
		while ( currPosition != std::wstring::npos )
		{
			std::string tmpName = pathToParse.substr( 0, currPosition );
			pathToParse = pathToParse.substr( currPosition + 1 );
			currPosition = pathToParse.find_first_of( TEXT('/') );

			if ( !tmpName.empty() )
			{
				nameList.push_back( tmpName );
			}
		}

		if ( !pathToParse.empty() )
		{
			// Add the remainer:
			nameList.push_back( pathToParse );
		}

		return ( nameList.size() > 1 );
	}
}